﻿#ifndef IntergerProc_h__2013_12_10__17_29
#define IntergerProc_h__2013_12_10__17_29

#include "df_macro.h"

namespace df
{

	template<class T>
	struct IType
	{
		typedef T Num;
	};

	template<>
	struct IType<bool>
	{
		typedef int Num;
	};

	template<>
	struct IType<int8_t>
	{
		typedef uint8_t Num;
	};

	template<>
	struct IType<int16_t>
	{
		typedef uint16_t Num;
	};

	template<>
	struct IType<int32_t>
	{
		typedef uint32_t Num;
	};

	//#if WIN32
	template<>
	struct IType<long>
	{
		typedef uint32_t Num;
	};
	//#endif

	template<>
	struct IType<int64_t>
	{
		typedef uint64_t Num;
	};



	template<class T>
	struct DigitType
	{
		typedef void No;
	};

	template<>
	struct DigitType<char>
	{
		typedef char Type;
	};

	template<>
	struct DigitType<int8_t>
	{
		typedef int8_t Type;
	};

	template<>
	struct DigitType<int16_t>
	{
		typedef int16_t Type;
	};

	template<>
	struct DigitType<bool>
	{
		typedef bool Type;
	};

	template<>
	struct DigitType<int32_t>
	{
		typedef int32_t Type;
	};

	//#if WIN32
	template<>
	struct DigitType<long>
	{
		typedef int32_t Type;
	};
	//#endif

	template<>
	struct DigitType<int64_t>
	{
		typedef int64_t Type;
	};

	template<>
	struct DigitType<uint8_t>
	{
		typedef uint8_t Type;
	};

	template<>
	struct DigitType<uint16_t>
	{
		typedef uint16_t Type;
	};

	template<>
	struct DigitType<uint32_t>
	{
		typedef uint32_t Type;
	};

	//#if WIN32
	template<>
	struct DigitType<unsigned long>
	{
		typedef uint32_t Type;
	};
	//#endif

	template<>
	struct DigitType<uint64_t>
	{
		typedef uint64_t Type;
	};


	//,typename DigitType<IT>::Type=0
	template<typename _CT, typename _IT>
	inline void StringToDigit(const df::BaseChar<_CT> & str, _IT & num)
	{
		static_assert(std::is_integral<_IT>::value, "number type must be integral");

		num = 0;
		int postive = 1;

		for (int i = 0; i < str.length_; i++)
		{
			if (str[i] >= 48 && str[i] <= 57)
			{
				num *= 10;
				num += str[i] - 48;
				continue;
			}

			if (!std::is_same<typename IType<_IT>::Num, _IT>::value)
			{
				if (str[i] == 45 && num == 0)
					postive = -1;
			}
		}

		if (!std::is_same<typename IType<_IT>::Num, _IT>::value)
		{
			num *= (_IT)postive;
		}
	}

	template<typename _CT, typename _IT>
	FORCEINLINE void StringHexToDigit(const df::BaseChar<_CT> & str, _IT & num)
	{
		static_assert(std::is_integral<_IT>::value, "number type must be integral");

		num = 0;

		for (int i = 0; i < str.length_; i++)
		{
			auto val = GetCharTable()[(str[i] & 0xFF)];
			num <<= 4;
			num |= (_IT)val;
		}

	}

	template<typename _CT>
	inline void StringToDigit(const df::BaseChar<_CT> & str, bool & num)
	{
		num = false;
		for (int i = 0; i < str.length_; i++)
		{
			if (str[i] >= 49 && str[i] <= 57)
			{
				num = true;
				break;
			}
		}
	}


	inline void StringToDigit(const df::BaseChar<char> & str, double & num)
	{
		num = df::StringToDouble(str);
	}
	inline void StringToDigit(const df::BaseChar<char> & str, float & num)
	{
		num = (float)df::StringToDouble(str);
	}

#ifdef _MSC_VER
	inline void StringToDigit(const df::BaseChar<wchar_t> & str, double & num)
	{
		num = df::StringToDouble(str);
	}
	inline void StringToDigit(const df::BaseChar<wchar_t> & str, float & num)
	{
		num = (float)df::StringToDouble(str);
	}
#endif

	template<typename _CT, typename _IT>
	void StringToDigit(const _CT * str, _IT & num)
	{
		StringToDigit(df::BaseChar<_CT>(str), num);
	}

	template<typename _CT, typename _IT>
	void StringToDigit(const std::basic_string<_CT> & str, _IT & num)
	{
		StringToDigit(df::BaseChar<_CT>(str), num);
	}

	template<typename _DigitType>
	struct DigitSize
	{
		enum {
			size = sizeof(_DigitType)* 4
		};
	};



	template<>
	struct DigitSize<float>
	{
		enum {
			size = 64
		};
	};

	template<>
	struct DigitSize<double>
	{
		enum {
			size = 64
		};
	};

	template<typename _DigitType, typename _CharT = TCHAR>
	class DigitProc
	{
	public:
		static const int maxSize_ = DigitSize<_DigitType>::size;
		_CharT char_[maxSize_];

		DigitProc()
		{
		}

		int Set(double pNum, int fraction)
		{
			return Set(char_, pNum, fraction);
		}

		static int Set(_CharT * char_, double pNum)
		{
			return df::Sprintf(char_, maxSize_, _T("%g"), pNum);
		}

		static int Set(_CharT * char_, double pNum, int fraction)
		{
			_CharT floatFormat[5];
			floatFormat[0] = DF_CHAR(_CharT, '%');
			floatFormat[1] = DF_CHAR(_CharT, '.');
			floatFormat[2] = df::CharSelect<_CharT>::GetTable()[fraction];
			floatFormat[3] = DF_CHAR(_CharT, 'g');
			floatFormat[4] = 0;
			return df::Sprintf(char_, maxSize_, floatFormat, pNum);
		}

		int Set(void * pNum)
		{
			return Set(char_, pNum);
		}
		///指针转为16进制
		static int Set(_CharT * char_, const void * pNum)
		{
			uintptr_t num = (uintptr_t)(pNum);

			int size_ = sizeof(pNum)* 2 + 2;;

			char_[0] = DF_CHAR(_CharT, '0');
			char_[1] = DF_CHAR(_CharT, 'x');

			for (int i = size_ - 1; i >= 2; i--)
			{
				char_[i] = df::CharSelect<_CharT>::GetTable()[num & 0xF];
				num >>= 4;
			}
			char_[size_] = 0;

			return size_;
		}

		template<typename _DT>
		int Set(_DT num)
		{
			return Set(char_, num);
		}

		template<typename _DT>
		df::BaseChar<_CharT> Get(_DT num)
		{
			auto len = Set(char_, num);
			return BaseChar<_CharT>(char_, len);
		}

		///数字类型转换为10进制
		template<typename _DT>
		static int Set(_CharT * char_, _DT num)
		{
			int size_ = 0;

			NumAbs(char_, num, size_);

			_CharT * numBuf = char_ + size_;
			///全部转换为无符号整数(避免NumAbs的缺陷,兼容-128,-32768.......)
			typename df::IType<_DigitType>::Num num2 = (typename df::IType<_DigitType>::Num)num;
			int cursor = 0;
			//获取整数
			do
			{
				numBuf[cursor] = df::CharSelect<_CharT>::GetTable()[num2 % 10];
				num2 /= 10;
				++cursor;
			} while (num2);

			size_ += cursor;
			//转换高低位
			_CharT c;
			for (int i = 0; i < cursor / 2; i++)
			{
				c = numBuf[i];
				numBuf[i] = numBuf[cursor - i - 1];
				numBuf[cursor - i - 1] = c;
			}

			numBuf[cursor] = 0;

			return size_;
		}
	private:
		///取绝对值,并向buf_中插入负号
		///当为char:-128,__int16:-32768.......时溢出,结果不变,这些特殊值要单独处理
		template<typename _DT>
		static inline void NumAbs(_CharT * char_, _DT & num, int & size_)
		{
			if (num < 0)
			{
				num = 0 - num;
				*char_ = DF_CHAR(_CharT, '-');
				++size_;
			}
		}
		static  inline void NumAbs(_CharT *, bool &, int &) { }
		static inline void NumAbs(_CharT *, uint16_t &, int &) { }
		static inline void NumAbs(_CharT *, uint32_t &, int &) { }
		static inline void NumAbs(_CharT *, uint64_t &, int &) { }


	};


}

#endif // IntergerProc_h__2013_12_10__17_29
